package me.base.utils.enums;

import cn.hutool.core.util.EnumUtil;
import lombok.experimental.UtilityClass;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description:
 * @author: Sylar
 * @date: 2021年10月06日 3:04 下午
 */
@UtilityClass
public class LableValueEnumUtil {

    public <E extends Enum<E>> int getEnumIndex(Class<E> enumType, E enumInstance) {
        if (enumInstance == null || enumType == null) return -1;
        for (int i = 0; i < enumType.getEnumConstants().length; i++) {
            if (enumInstance == enumType.getEnumConstants()[i]) {
                return i;
            }
        }
        return -1;
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> E fromValue(Class<E> enumType, V value) {
        if (value == null || enumType == null) return null;
        Optional<E> optional = Stream.of(enumType.getEnumConstants()).filter(e -> e.getValue().equals(value)).findFirst();
        return optional.orElse(null);
    }

    public <E extends Enum<E>> E fromLabel(Class<E> enumType, String label) {
        if (label == null || enumType == null) return null;
        return EnumUtil.fromString(enumType, label);
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> boolean equals(E e1, E e2) {
        if (e1 == null || e2 == null) {
            return false;
        }
        return e1.getValue().equals(e2.getValue());
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> Set<V> getValues(Class<E> enumType) {
        return getMap(enumType).keySet();
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> Collection<String> getLabels(Class<E> enumType) {
        return getMap(enumType).values();
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> boolean containsCode(Class<E> enumType, V value) {
        return getMap(enumType).containsKey(value);
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> boolean containsLabel(Class<E> enumType, String label) {
        return getMap(enumType).containsValue(label);
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> Set<E> getEnums(Class<E> enumType) {
        return Stream.of(enumType.getEnumConstants()).collect(Collectors.toSet());
    }

    public <V extends Serializable, E extends Enum<E> & LabelValue<V>> Map<V, String> getMap(Class<E> enumType) {
        assert enumType != null;
        return Stream.of(enumType.getEnumConstants()).collect(Collectors.toMap(LabelValue::getValue, LabelValue::getLabel));
    }

}
